package com.html2rss.models;

import com.html2rss.core.exceptions.HtmlToRssException;
import com.html2rss.core.DomHelper;
import org.w3c.dom.Node;

import javax.xml.xpath.XPathExpressionException;
import java.util.ArrayList;
import java.util.List;


/**
 * User: vvs
 * Date: 13.04.2007
 * Time: 1:33:26
 */
public class Query {
    private List<String> relQuiries;
    private List<String> pathToRoot;
    private List<Integer> pathToRootInd;
    private String path;


    public List<String> getPathToRoot() {
        return pathToRoot;
    }

    public Query(List<Node> leafes) throws HtmlToRssException {
        Node commonParent = DomHelper.findCommonParent(leafes);
        buildRelQuiries(commonParent, leafes);
        buildRootPath(commonParent);
    }


    public Query(List<String> relQuiries, List<String> pathToRoot,List<Integer> pathToRootInd) {
        this.relQuiries = new ArrayList<String>(relQuiries);
        this.pathToRoot = new ArrayList<String>(pathToRoot) ;
        this.pathToRootInd = new ArrayList<Integer>(pathToRootInd);
    }

    private void buildRootPath(Node commonParent) throws HtmlToRssException {
        pathToRoot = new ArrayList<String>();
        pathToRootInd = new ArrayList<Integer>();
        while (commonParent != null) {
            pathToRootInd.add(0, DomHelper.getNodePosition(commonParent));
            pathToRoot.add(0, commonParent.getNodeName());
            commonParent = commonParent.getParentNode();
        }
    }

    private void buildRelQuiries(Node commonParent, List<Node> leafes) throws HtmlToRssException {
        relQuiries = new ArrayList<String>();
        for (Node n : leafes) {
            String s = "";
            Node next = n;
            while (next != commonParent) {
                int nodePosition = DomHelper.getNodePosition(next);
                if (nodePosition >= 0) {
                    s = next.getNodeName() + "[" + (nodePosition ) + "]" + (next==n?"":"/") + s;
                } else {
                    s = next.getNodeName() + (next==n?"":"/") + s;
                }
                next = next.getParentNode();
            }
            relQuiries.add(s);
        }
    }


    public List<String> getRelQuiries() {
        return relQuiries;
    }

    public void setRelQuiries(List<String> relQuiries) {
        this.relQuiries = relQuiries;
    }


    public String compile() {
        String path= "";
        for (int i=0; i<getPathToRoot().size(); i++ ) {
            String s = getPathToRoot().get(i);
            if (s.equals("/")) {
                path += "/";
            } else {
                path += "/"+ s;
            }
            if (pathToRootInd.get(i) >=0) {
                path += "[" + getPathToRootInd().get(i) + "]";
            }
        }
        path+="[";
        for (int i=0; i<getRelQuiries().size(); i++) {
            path += getRelQuiries().get(i);
            if (i!=getRelQuiries().size() - 1) {
                path+=" and ";
            }
        }
        path +="]";
        System.out.println("query = "+path);
        return this.path = path;
    }

    public List <Node> execute (Node node) throws XPathExpressionException {
        compile();
        return DomHelper.getXPathNodeList(this.path, node);
    }


    public Object clone () {
        Query q = new Query(relQuiries, getPathToRoot(), getPathToRootInd());
        for (int i=0; i<q.getRelQuiries().size(); i++) {
            q.getRelQuiries().set(i, new String(q.getRelQuiries().get(i)));
        }
        for (int i=0; i<q.getPathToRoot().size(); i++) {
            q.getPathToRoot().set(i, new String(q.getPathToRoot().get(i)));
            q.getPathToRootInd().set(i, new Integer(q.getPathToRootInd().get(i)));
        }
        return q;
    }


    public List<Integer> getPathToRootInd() {
        return pathToRootInd;
    }

    public void setPathToRootInd(List<Integer> pathToRootInd) {
        this.pathToRootInd = pathToRootInd;
    }


    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public void setPathToRoot(List<String> pathToRoot) {
        this.pathToRoot = pathToRoot;
    }
}
